﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Media3D;

namespace Topographic_Explorer
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }


        private void openButton_Click(object sender, RoutedEventArgs e)
        {
            ClearViewport();                                // Clear the viewport of any leftovers.
            Model3DGroup topography = new Model3DGroup();   // Define the model group for our topography
            Point3D[,] points = GetRandomTopographyPoints();
            for (int z = 0; z < 98; z++)
            {
                for (int x = 0; x < 98; x++)
                {
                    topography.Children.Add(        // The first triangle.
                        CreateTriangleModel(
                                points[x, z],      // Our base point
                                points[x, z + 1], // The point 10 away from it (So, in the next "Column", the tip!)
                                points[x + 1, z])  // The point beside the base.
                    );
                    topography.Children.Add(        // The second triangle.
                        CreateTriangleModel(
                                points[x + 1, z],  // The point beside our base.
                                points[x, z + 1], // The tip.
                                points[x + 1, z + 1]) // The point beside the tip.
                    );
                }
            }
            ModelVisual3D model = new ModelVisual3D();
            ModelVisual3D map = new ModelVisual3D();
            model.Content = topography;
            map.Content = topography;
            this.cameraViewport.Children.Add(model);
            this.mapViewport.Children.Add(map);
        }

        private Point3D[,] GetRandomTopographyPoints()
        {
            //create a 100x100 topography.
            Point3D[,] points = new Point3D[100, 100];
            Random r = new Random();
            double y;
            double denom = 1000;
            for (int z = 0; z < 100; z++)
            {
                for (int x = 0; x < 100; x++)
                {
                    y = Convert.ToDouble(r.Next(1, 999)) / denom;
                    points[x, z] = new Point3D(x, y, z);
                }
            }
            return points;
        }

        private Model3DGroup CreateTriangleModel(Point3D p0, Point3D p1, Point3D p2)
        {
            MeshGeometry3D mesh = new MeshGeometry3D();
            mesh.Positions.Add(p0);
            mesh.Positions.Add(p1);
            mesh.Positions.Add(p2);
            mesh.TriangleIndices.Add(0);
            mesh.TriangleIndices.Add(1);
            mesh.TriangleIndices.Add(2);
            Vector3D normal = CalculateNormal(p0, p1, p2);
            mesh.Normals.Add(normal);
            mesh.Normals.Add(normal);
            mesh.Normals.Add(normal);
            Material material = new DiffuseMaterial(
                new SolidColorBrush(Colors.DarkKhaki));
            GeometryModel3D model = new GeometryModel3D(
                mesh, material);
            Model3DGroup group = new Model3DGroup();
            group.Children.Add(model);
            return group;
        }
        private Vector3D CalculateNormal(Point3D p0, Point3D p1, Point3D p2)
        {
            Vector3D v0 = new Vector3D(
                p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
            Vector3D v1 = new Vector3D(
                p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z);
            return Vector3D.CrossProduct(v0, v1);
        }

        private void ClearViewport()
        {
            ModelVisual3D m;
            for (int i = cameraViewport.Children.Count - 1; i >= 0; i--)
            {
                m = (ModelVisual3D)cameraViewport.Children[i];
                if (m.Content is DirectionalLight == false)
                {
                    cameraViewport.Children.Remove(m);
                }
            }
            for (int i = mapViewport.Children.Count - 1; i >= 0; i--)
            {
                m = (ModelVisual3D)mapViewport.Children[i];
                if (m.Content is DirectionalLight == false)
                {
                    mapViewport.Children.Remove(m);
                }
            }
        }

        private void Zoom(object sender, MouseWheelEventArgs e)
        {
            PerspectiveCamera camera = (PerspectiveCamera)cameraViewport.Camera;
            camera.LookDirection = new Vector3D(camera.LookDirection.X, camera.LookDirection.Y + e.Delta/1000, camera.LookDirection.Z);
        }


    }
}
